MODULE_NAME='DTV HR21 Serial Driver' (Dev dvDTV_Rcvr, Dev vdvDTV_Rcvr)
(***********************************************************)
(***********************************************************)
(*  FILE_LAST_MODIFIED_ON: 04/04/2006  AT: 11:33:16        *)
(***********************************************************)
(* System Type : NetLinx                                   *)
(***********************************************************)
(* REV HISTORY:                                            *)
(***********************************************************)
(*
    $History: $
*)    
//#DEFINE DEBUG
(***********************************************************)
(*          DEVICE NUMBER DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_DEVICE

(***********************************************************)
(*               CONSTANT DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_CONSTANT
cnMaxDebugLen = 200;

Long lChannelFBTimeLineID = 1001;
Long lChannelFBTimes[] = {10000};
nUpdateTimeQty = 1;

Char cnHeader[] = {$FA,$A5}
cnKeyToggle = $00
cnKeyUp = $01
cnKeyDown = $02

Integer nChannels[]=
{
	1,   // 1- cnSER_Play
	2,   // 2- cnSER_Stop
	3,   // 3- cnSER_Pause
	4,   // 4- cnSER_ScanFwd
	5,   // 5- cnSER_ScanRev
	8,   // 6- cnSER_Record
	9,   // 7- cnSER_PowerToggle
	10,  // 8- cnSER_0
	11,  // 9- cnSER_1
	12,  // 10- cnSER_2
	13,  // 11- cnSER_3
	14,  // 12- cnSER_4
	15,  // 13- cnSER_5
	16,  // 14- cnSER_6
	17,  // 15- cnSER_7
	18,  // 16- cnSER_8
	19,  // 17- cnSER_9
	20,  // 18- cnSER_Dash
	21,  // 19- cnSER_Enter          
	22,  // 20- cnSER_ChanUp
	23,  // 21- cnSER_ChanDn
	27,  // 22- cnSER_PowerOn
	28,  // 23- cnSER_PowerOff
	30,  // 24- cnSER_Jump
	42,  // 25- cnSER_Back
	45,  // 26- cnSER_Up
	46,  // 27- cnSER_Down
	47,  // 28- cnSER_Left
	48,  // 29- cnSER_Right
	49,  // 30- cnSER_Select
	51,  // 31- cnSER_Exit
	56,  // 32- cnSER_Guide
	57,  // 33- cnSER_Replay
	60,  // 34- cnSER_Red
	61,  // 35- cnSER_Green
	62,  // 36- cnSER_Yellow
	63,  // 37- cnSER_Blue
	64,  // 38- cnSER_Advance
	65,  // 39- cnSER_Menu
	66,  // 40- cnSER_List
	67,  // 41- cnSER_Info
	54,  // 42- cnSER_Active
	99   // 43- cnSER_Format
}              

(***********************************************************)
(*              DATA TYPE DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_TYPE

(***********************************************************)
(*               VARIABLE DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_VARIABLE
Volatile Char cnSerialCommands[43][5];

Volatile Char strCommandBuffer[200]
Volatile Char strChannelFBBuffer[200]

Volatile Integer nCurrentChannel
Volatile Integer nCurrentSubChannel

Volatile Char strJunk[20];

Volatile Integer nSerialCommandLen;

(***********************************************************)
(*               LATCHING DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_LATCHING

(***********************************************************)
(*       MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW           *)
(***********************************************************)
DEFINE_MUTUALLY_EXCLUSIVE

(***********************************************************)
(*        SUBROUTINE/FUNCTION DEFINITIONS GO BELOW         *)
(***********************************************************)
(* EXAMPLE: DEFINE_FUNCTION <RETURN_TYPE> <NAME> (<PARAMETERS>) *)
(* EXAMPLE: DEFINE_CALL '<NAME>' (<PARAMETERS>) *)

Define_Call 'DEBUG_OUTPUT' (Integer nLine, Char strData[])
{
	#IF_DEFINED DEBUG
	Char strTempData[200];
	Integer nLen;
	
	nLen = Length_String(strData)
	If (nLen < cnMaxDebugLen)
	{
		Send_String 0,"__FILE__,' Line:',Itoa(nLine),' ',strData";
	}
	Else
	{
		strTempData = Left_String(strData,cnMaxDebugLen);
		strData = Right_String(strData,nLen-cnMaxDebugLen);
		Send_String 0,"__FILE__,' Line:',Itoa(nLine),' ',strTempData";
		Send_String 0,"'Continued: ',strData";
	}
	#END_IF
}

Define_Call 'GOTO_CHANNEL' (Integer nChan, Integer nSubChan)
{
	Call 'DEBUG_OUTPUT'(__LINE__,"'nChan:',Itoa(nChan),' nSubChan',Itoa(nSubChan)")
	If (nSubChan == 0)
	{
		Send_String dvDTV_Rcvr,"$FA,$A6,nChan/256,nChan mod 256,$FF,$FF"
	}
	Else
	{
		Send_String dvDTV_Rcvr,"$FA,$A6,nChan/256,nChan mod 256,nSubChan/256,nSubChan mod 256"
	}
}
(***********************************************************)
(*                STARTUP CODE GOES BELOW                  *)
(***********************************************************)
DEFINE_START
// RDM One way serial so no need to poll.
//Timeline_Create(lChannelFBTimeLineID, lChannelFBTimes, nUpdateTimeQty, Timeline_Relative, Timeline_Repeat);


cnSerialCommands[1] = "$01,$B2"//	cnSER_Play
cnSerialCommands[2] = "$01,$B3"//	cnSER_Stop
cnSerialCommands[3] = "$01,$B0"//	cnSER_Pause
cnSerialCommands[4] = "$01,$B4"//	cnSER_ScanFwd
cnSerialCommands[5] = "$01,$B1"//	cnSER_ScanRev
cnSerialCommands[6] = "$01,$B5"//	cnSER_Record
cnSerialCommands[7] = "$01,$D5"//	cnSER_PowerToggle
cnSerialCommands[8] = "$01,$E0"//	cnSER_0
cnSerialCommands[9] = "$01,$E1"//	cnSER_1
cnSerialCommands[10] = "$01,$E2"//	cnSER_2
cnSerialCommands[11] = "$01,$E3"//	cnSER_3
cnSerialCommands[12] = "$01,$E4"//	cnSER_4
cnSerialCommands[13] = "$01,$E5"//	cnSER_5
cnSerialCommands[14] = "$01,$E6"//	cnSER_6
cnSerialCommands[15] = "$01,$E7"//	cnSER_7
cnSerialCommands[16] = "$01,$E8"//	cnSER_8
cnSerialCommands[17] = "$01,$E9"//	cnSER_9
cnSerialCommands[18] = "$01,$A5"//	cnSER_Dash
cnSerialCommands[19] = "$01,$A0"//	cnSER_Enter
cnSerialCommands[20] = "$01,$D1"//	cnSER_ChanUp
cnSerialCommands[21] = "$01,$D2"//	cnSER_ChanDn
cnSerialCommands[22] = "$01,$C5"//  cnSER_PowerOn
cnSerialCommands[23] = "$01,$D0"//  cnSER_PowerOff
cnSerialCommands[24] = "$01,$D6"//	cnSER_Jump
cnSerialCommands[25] = "$01,$A4"//	cnSER_Back
cnSerialCommands[26] = "$01,$9C"//	cnSER_Up
cnSerialCommands[27] = "$01,$9D"//	cnSER_Down
cnSerialCommands[28] = "$01,$9B"//	cnSER_Left
cnSerialCommands[29] = "$01,$9A"//	cnSER_Right
cnSerialCommands[30] = "$01,$C3"//	cnSER_Select
cnSerialCommands[31] = "$01,$D4"//	cnSER_Exit
cnSerialCommands[32] = "$01,$D3"//	cnSER_Guide
cnSerialCommands[33] = "$01,$B6"//	cnSER_Replay
cnSerialCommands[34] = "$01,$EA"//	cnSER_Red
cnSerialCommands[35] = "$01,$EC"//	cnSER_Green
cnSerialCommands[36] = "$01,$EB"//	cnSER_Yellow
cnSerialCommands[37] = "$01,$ED"//	cnSER_Blue
cnSerialCommands[38] = "$01,$B7"//	cnSER_Advance
cnSerialCommands[39] = "$01,$F7"//	cnSER_Menu
cnSerialCommands[40] = "$01,$A3"//	cnSER_List
cnSerialCommands[41] = "$01,$A1"//	cnSER_Info
cnSerialCOmmands[42] = "$01,$A2"//  cnSER_Active
cnSerialCommands[43] = "$01,$F8"//  cnSER_Format

nSerialCommandLen = Max_Length_Array(cnSerialCommands)
(***********************************************************)
(*                THE EVENTS GO BELOW                      *)
(***********************************************************)
DEFINE_EVENT

Timeline_Event[lChannelFBTimeLineID]
{
	Send_String dvDTV_Rcvr,"$FA,$87" // current channel
}

Data_Event[dvDTV_Rcvr]
{
  Online:
  {
    Send_Command dvDTV_Rcvr,"'SET BAUD 9600,N,8,1 485 DISABLE'"
    Send_Command dvDTV_Rcvr,"'RXON'"
    Send_Command dvDTV_Rcvr,"'HSOFF'"
    Send_Command dvDTV_Rcvr,"'XOFF'"
	}
	String:
	{
		Integer nPos, nSuccessPos, nTempChannel, nTempSubChannel
		
		strChannelFBBuffer= "strChannelFBBuffer,Data.text"
//		If (Find_String(strChannelFBBuffer,"$FF",1))
//		{
//			strJunk = Remove_String(strChannelFBBuffer,"$FF",1) // error
//		}
		nPos = Find_String(strChannelFBBuffer,"$F0",1)
		Call 'DEBUG_OUTPUT' (__Line__,"'nPos:',Itoa(nPos),' strChannelFBBuffer:',strChannelFBBuffer")
		nSuccessPos = Find_String(strChannelFBBuffer,"$F4",nPos)
		If (nPos && nSuccessPos == nPos + 5)
		{
			nTempChannel = (strChannelFBBuffer[nPos+1]*256) + strChannelFBBuffer[nPos+2]
			nTempSubChannel = (strChannelFBBuffer[nPos+3]*256) + strChannelFBBuffer[nPos+4]
			If (nTempSubChannel == 65535) // will be 65535 if sub channel is 0.
			{
				nTempSubChannel = 0
			}
			strJunk = Remove_String(strChannelFBBuffer,"$F4",1)
			If (nTempChannel != nCurrentChannel || nTempSubChannel != nCurrentSubChannel)
			{
				nCurrentChannel = nTempChannel
				nCurrentSubChannel = nTempSubChannel
				Send_String vdvDTV_Rcvr,"'CHAN=',Itoa(nCurrentChannel),'.',Itoa(nCurrentSubChannel)"
			}
		}
		Else If (nPos && nSuccessPos)
		{
			Call 'DEBUG_OUTPUT' (__Line__,"'nPos:',Itoa(nPos),' nSuccessPos:',Itoa(nSuccessPos)")
			strJunk = Remove_String(strChannelFBBuffer,"$F4",1)
		}
	}
}

Data_Event[vdvDTV_Rcvr]
{
	Command:
	{
		strCommandBuffer = Data.Text
		Call 'DEBUG_OUTPUT' (__Line__,"'strCommandBuffer:',strCommandBuffer")
		IF (Find_String(strCommandBuffer,'XCH',1))
		{
			strJunk = Remove_String(strCommandBuffer,'XCH',1)
			Call 'GOTO_CHANNEL' (Atoi(strCommandBuffer),0)
		}
	}
}

Channel_Event[vdvDTV_Rcvr,nChannels]
{
	On:
	{
		//Call 'DEBUG_OUTPUT' (__LINE__, "'Entered Channel On Event.  nChannels:',Itoa(Get_Last(nChannels))");
		If (Get_Last(nChannels) <= nSerialCommandLen)
		{
			Send_String dvDTV_Rcvr,"cnHeader,cnKeyDown,cnSerialCommands[Get_Last(nChannels)]"
			Call 'DEBUG_OUTPUT' (__LINE__, "'cnSerialCommands[',Itohex(Get_Last(nChannels)),'] $',Itohex(cnSerialCommands[Get_Last(nChannels)][1]),',$',Itohex(cnSerialCommands[Get_Last(nChannels)][2])")
		}
	}
	Off:
	{
		//Call 'DEBUG_OUTPUT' (__LINE__, "'Entered Channel Off Event.  nChannels:',Itoa(Get_Last(nChannels))");
		If (Get_Last(nChannels) <= nSerialCommandLen)
		{
			Send_String dvDTV_Rcvr,"cnHeader,cnKeyUp,cnSerialCommands[Get_Last(nChannels)]"
			Call 'DEBUG_OUTPUT' (__LINE__, "'cnSerialCommands[',Itohex(Get_Last(nChannels)),'] $',Itohex(cnSerialCommands[Get_Last(nChannels)][1]),',$',Itohex(cnSerialCommands[Get_Last(nChannels)][2])")
		}
	}
}

(***********************************************************)
(*            THE ACTUAL PROGRAM GOES BELOW                *)
(***********************************************************)
DEFINE_PROGRAM

(***********************************************************)
(*                     END OF PROGRAM                      *)
(*        DO NOT PUT ANY CODE BELOW THIS COMMENT           *)
(***********************************************************)
